import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import Job from 'src/entities/job.entity';
import { Brackets, In, Repository } from 'typeorm';
import { CreateJobDto, FindJobDto, SearchJobDto, UpdateJobDto } from './job.dto';
import Position from 'src/entities/position.entity';
import Company from 'src/entities/company.entity';
import { isEmpty } from 'lodash';
import { ApiException } from 'src/core/exceptions/api.exception';
import User from 'src/entities/user.entity';

@Injectable()
export class JobService {
  constructor(
    @InjectRepository(Job) private jobRepository: Repository<Job>,
    @InjectRepository(Position) private positionRepository: Repository<Position>,
    @InjectRepository(Company) private companyRepository: Repository<Company>,
    @InjectRepository(User) private userRepository: Repository<User>,
  ) {}

  // 根据条件查询所有岗位
  async find(query: FindJobDto) {
    const { page, size, hot, name, salary, companyName } = query;

    const queryBuilder = this.jobRepository
      .createQueryBuilder('job')
      .leftJoinAndSelect('job.position', 'position')
      .leftJoinAndSelect('job.company', 'company')
      .orderBy('job.createdAt', 'DESC')
      .skip(size * (page - 1))
      .take(size)
      .select([
        'job.id',
        'job.salary',
        'job.experience',
        'job.education',
        'job.enableStatus',
        'job.createdAt',
        'position.id',
        'position.name',
        'company.id',
        'company.userId',
        'company.name',
        'company.fullName',
        'company.scale',
        'company.nature',
      ]);

    // 根据职位名称查询
    if (name !== undefined) {
      const hotPositionIds = await this.positionRepository
        .createQueryBuilder('position')
        .where('position.name Like :name', { name: `%${name}%` })
        .select('position.id')
        .getMany()
        .then((positions) => positions.map((position) => position.id));

      if (hotPositionIds.length > 0) {
        queryBuilder.andWhere('position.id IN (:ids)', { ids: hotPositionIds });
      } else {
        return { list: [], count: 0 };
      }
    }
    if (salary !== undefined) {
      queryBuilder.andWhere('job.salary = :salary', { salary });
    }
    // 根据公司名称查询
    if (companyName !== undefined) {
      const companyIds = await this.companyRepository
        .createQueryBuilder('company')
        .where('company.fullName Like :companyName', { companyName: `%${companyName}%` })
        .select('company.id')
        .getMany()
        .then((results) => results.map((item) => item.id));

      if (companyIds.length > 0) {
        queryBuilder.andWhere('company.id IN (:ids)', { ids: companyIds });
      } else {
        return { list: [], count: 0 };
      }
    }

    if (hot !== undefined) {
      const hotPositionIds = await this.positionRepository
        .createQueryBuilder('position')
        .where('position.hot = :hot', { hot: 1 })
        .select('position.id')
        .getMany()
        .then((positions) => positions.map((position) => position.id));

      if (hotPositionIds.length > 0) {
        queryBuilder.andWhere('position.id IN (:ids)', { ids: hotPositionIds });
      }
    }

    const [list, count] = await queryBuilder.getManyAndCount();

    // 获取用户信息
    const userIds = list.map((item) => item.company.userId);
    const users = await this.userRepository.find({
      where: { id: In(userIds) },
      select: ['id', 'nickname', 'avatar'],
    });

    const jobList = list.map((item) => {
      const user = users.find((user) => user.id === item.company.userId);
      return { ...item, user };
    });

    return { list: jobList, count };
  }

  // 根据公司ID查询岗位列表
  async findJobsByCompanyId(companyId: number) {
    return await this.jobRepository.find({
      where: { company: { id: companyId } },
      relations: ['position'],
    });
  }

  // 查询详细
  async findOne(id: number) {
    return await this.jobRepository.findOne({
      where: { id },
      relations: ['position'],
    });
  }

  // 岗位信息详情
  async jobInfo(id: number) {
    const queryBuilder = this.jobRepository
      .createQueryBuilder('job')
      .leftJoinAndSelect('job.position', 'position')
      .leftJoinAndSelect('job.company', 'company')
      .orderBy('job.createdAt', 'DESC')
      .where('job.enable_status = 1')
      .andWhere('job.id = :id', { id })
      .select([
        'job.id',
        'job.salary',
        'job.experience',
        'job.education',
        'job.duty',
        'job.require',
        'job.enableStatus',
        'job.createdAt',
        'position.id',
        'position.name',
        'company.id',
        'company.logo',
        'company.address',
        'company.name',
        'company.scale',
        'company.nature',
      ]);

    return queryBuilder.getOne();
  }

  // 创建
  async create(createJobDto: CreateJobDto) {
    const { companyId, positionId, ...info } = createJobDto;

    const company = await this.companyRepository.findOne({ where: { id: companyId } });
    const position = await this.positionRepository.findOne({ where: { id: positionId } });

    const job = this.jobRepository.create({ ...info, company, position });
    await this.jobRepository.save(job);
  }

  // 更新
  async update(updateJobDto: UpdateJobDto) {
    const { id, positionId, ...info } = updateJobDto;

    const job = await this.jobRepository.findOne({ where: { id } });
    if (isEmpty(job)) {
      throw new ApiException(10010);
    }

    const position = await this.positionRepository.findOne({ where: { id: positionId } });
    if (isEmpty(position)) {
      throw new ApiException(10011);
    }

    const newJob = this.jobRepository.merge(job, { position, ...info });
    await this.jobRepository.save(newJob);
  }

  // 搜索
  async search(searchJobDto: SearchJobDto) {
    const { ids, salary, address } = searchJobDto;

    const queryBuilder = this.jobRepository
      .createQueryBuilder('job')
      .leftJoinAndSelect('job.position', 'position')
      .leftJoinAndSelect('job.company', 'company')
      .orderBy('job.createdAt', 'DESC')
      .where('job.enable_status = 1')
      .select([
        'job.id',
        'job.salary',
        'job.experience',
        'job.education',
        'job.enableStatus',
        'job.createdAt',
        'position.id',
        'position.name',
        'company.id',
        'company.userId',
        'company.name',
        'company.scale',
        'company.nature',
      ])
      .where((qb) => {
        qb.andWhere('job.position_id IN (:ids)', { ids });
        if (salary !== '全部') {
          qb.andWhere(
            new Brackets((subQb) => {
              subQb
                .where('job.salary = :salary', { salary })
                .orWhere('job.salary = :default', { default: '面议' });
            }),
          );
        }
        if (address !== undefined) {
          qb.andWhere('job.city = :address', { address });
        }
      });

    const list = await queryBuilder.getMany();

    // 获取用户信息
    const userIds = list.map((item) => item.company.userId);
    const users = await this.userRepository.find({
      where: { id: In(userIds) },
      select: ['id', 'nickname', 'avatar'],
    });

    const jobList = list.map((item) => {
      const user = users.find((user) => user.id === item.company.userId);
      return { ...item, user };
    });

    return jobList;
  }
}
